package com.onstar.cn.framework.network.entity;

import android.content.Context;

import com.onstar.cn.framework.network.NoSSLv3SocketFactory;
import com.onstar.cn.framework.utils.CertString;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import okhttp3.OkHttpClient;

/**
 * Created by OnStar on 2017/4/18.
 */

public class SSLConnectionFactory {

    //    public static final String[] capInputNames = {"m_prd.cer","portal_prd.cer","prd.cer"};
    public static final String[] CAPINPUTNAMES_PROD = {CertString.M_PRD, CertString.PORTAL_PRD, CertString.PRD};
    public static final String[] CAPINPUTNAMES_IDT1 = {CertString.PORTAL_TEST, CertString.TEST_CER};
    public static final String[] CAPINPUTNAMES_VV2 = {CertString.PORTAL_TEST, CertString.TEST_CER, CertString.VV2_API};
    public static String[] capInputNames = CAPINPUTNAMES_IDT1;


    public static HttpsURLConnection createStrictSSLConnection(Context mContext, RequestEntity requestEntity) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
//        InputStream caInput = null;
        InputStream[] caInputs = new InputStream[capInputNames.length];
        HttpsURLConnection urlConnection = null;
        try {
            String weburl = requestEntity.getUrl();
//            CertificateFactory cf = CertificateFactory.getInstance("X.509");
//            LogManager.getInstance().d("" + requestEntity.getUrl());
//            caInput = new BufferedInputStream(mContext.getAssets().open("prd.cer"));
//            Certificate ca;
//            ca = cf.generateCertificate(caInput);
//            System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
//
//            String keyStoreType = KeyStore.getDefaultType();
//            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
//            keyStore.load(null, null);
//            keyStore.setCertificateEntry("ca", ca);
//            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
//            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
//            tmf.init(keyStore);

            for (int i = 0; i < capInputNames.length; i++) {
//                caInputs[i] = new BufferedInputStream(mContext.getAssets().open(capInputNames[i]));
                caInputs[i] = new ByteArrayInputStream(capInputNames[i].getBytes());
            }
            SSLContext context = SSLContext.getInstance("TLSv1");
            context.init(null, prepareTrustManager(caInputs), null);

            URL url = new URL(weburl);
            urlConnection = (HttpsURLConnection) url.openConnection();
            urlConnection.setSSLSocketFactory(context.getSocketFactory());
            urlConnection.setRequestMethod(requestEntity.getMethod());

        } catch (CertificateException e1) {
            throw e1;
        } catch (NoSuchAlgorithmException e2) {
            throw e2;
        } catch (KeyStoreException e3) {
            throw e3;
        } catch (IOException e4) {
            throw e4;
        } catch (KeyManagementException e5) {
            throw e5;
        } catch (Exception e6) {
            throw e6;
        } finally {
            for (InputStream caInput : caInputs) {
                if (caInput != null) {
                    try {
                        caInput.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return urlConnection;
    }

    public static OkHttpClient.Builder createStrictSSLConnection(OkHttpClient.Builder builder) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
//        InputStream caInput = null;
        InputStream[] caInputs = new InputStream[capInputNames.length];

        try {
            for (int i = 0; i < capInputNames.length; i++) {
//                caInputs[i] = new BufferedInputStream(mContext.getAssets().open(capInputNames[i]));
                caInputs[i] = new ByteArrayInputStream(capInputNames[i].getBytes());
            }
            SSLContext context = SSLContext.getInstance("TLSv1");
            context.init(null, prepareTrustManager(caInputs), null);
            builder.sslSocketFactory(context.getSocketFactory());

        } catch (CertificateException e1) {
            throw e1;
        } catch (NoSuchAlgorithmException e2) {
            throw e2;
        } catch (KeyStoreException e3) {
            throw e3;
        } catch (IOException e4) {
            throw e4;
        } catch (KeyManagementException e5) {
            throw e5;
        } catch (Exception e6) {
            throw e6;
        } finally {
            for (InputStream caInput : caInputs) {
                if (caInput != null) {
                    try {
                        caInput.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return builder;
    }

    private static TrustManager[] prepareTrustManager(InputStream... certificates) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException {
        if (certificates == null || certificates.length <= 0) return null;
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            int index = 0;
            for (InputStream is : certificates) {
                String certificateAlias = Integer.toString(index++);
                Certificate certificate = certificateFactory.generateCertificate(is);
                keyStore.setCertificateEntry(certificateAlias, certificate);
                try {
                    if (is != null)
                        is.close();
                } catch (IOException ignored) {
                }
            }
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            return trustManagerFactory.getTrustManagers();
            // TODO: 2016/11/11 针对有效期异常导致校验失败的情况，目前没有完美的解决方案
//            TrustManager[] keyStoreTrustManagers = trustManagerFactory.getTrustManagers();
//            return getNotValidateTimeTrustManagers((X509TrustManager[]) keyStoreTrustManagers);
        } catch (CertificateException e1) {
            throw e1;
        } catch (NoSuchAlgorithmException e2) {
            throw e2;
        } catch (KeyStoreException e3) {
            throw e3;
        } catch (IOException e4) {
            throw e4;
        }
    }

//    public static HttpsURLConnection createStrictVerifyHostSSLConnection(Context context, final RequestEntity requestEntity) throws CertificateException, NoSuchAlgorithmException, KeyManagementException, ProtocolException, IOException {
//        HttpsURLConnection connection = null;
//        try {
//            InputStream certInput = new BufferedInputStream(context.getAssets().open("myWebsite.cer"));
//            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
//            final X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(certInput);
//
//            TrustManager[] trustManagers = new TrustManager[]{
//                    new X509TrustManager() {
//                        @Override
//                        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//
//                        }
//
//                        @Override
//                        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
//
//                            if (x509Certificates.length < 0) {
//                                throw new IllegalArgumentException("");
//                            }
//                            for (X509Certificate cert : x509Certificates) {
//                                cert.checkValidity();
//                                try {
//                                    Log.d("ssl connection", "cert" + cert.getPublicKey());
//                                    Log.d("ssl connection", "x509Certificate" + x509Certificate.getPublicKey());
//                                    cert.verify(x509Certificate.getPublicKey());
//                                } catch (Exception e) {
//                                    e.printStackTrace();
//                                    Log.e("", e.getMessage());
//                                }
//                            }
//
//                        }
//
//                        @Override
//                        public X509Certificate[] getAcceptedIssuers() {
//                            return new X509Certificate[0];
//                        }
//                    }
//            };
//            SSLContext sllContext = SSLContext.getInstance("TLSv1");
//            sllContext.init(null, trustManagers, null);
//            URL url = new URL(requestEntity.getUrl());
//            connection = (HttpsURLConnection) url.openConnection();
//            connection.setSSLSocketFactory(sllContext.getSocketFactory());
//            final HostnameVerifier hostnameVerifier = new HostnameVerifier() {
//                @Override
//                public boolean verify(String s, SSLSession sslSession) {
//                    HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
//                    Boolean result = hv.verify("*.shanghaionstar.com", sslSession);
//                    return result;
//                }
//            };
//            connection.setHostnameVerifier(hostnameVerifier);
//        } catch (CertificateException e1) {
//            throw e1;
//        } catch (NoSuchAlgorithmException e2) {
//            throw e2;
//        } catch (KeyManagementException e3) {
//            throw e3;
//        } catch (MalformedURLException e4) {
//            throw e4;
//        }
//        return connection;
//
//    }

    public static HttpsURLConnection createCommonSSLConnection(RequestEntity requestEntity) throws NoSuchAlgorithmException, MalformedURLException, KeyManagementException, ProtocolException, IOException {
        HttpsURLConnection conn = null;
        SSLContext sslcontext = null;
        try {
            sslcontext = SSLContext.getInstance("TLSv1");
            URL requestUrl = new URL(requestEntity.getUrl());
            sslcontext.init(null, null, null);
            SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory());
            HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory);
            conn = (HttpsURLConnection) requestUrl.openConnection();
            conn.setRequestMethod(requestEntity.getMethod());
        } catch (NoSuchAlgorithmException e) {
            throw e;
        } catch (MalformedURLException e) {
            throw e;
        } catch (KeyManagementException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        }
        return conn;
    }


}
